vue源码-1.准备知识


参考文章

vue
vue技术内幕
github-learnVue
手动实现mvvm
其他
购买视频

节点(Node)

包含document, Element, Attr, Text: 依次是html节点,元素节点,属性节点,文本节点

1
2
3
4
5
6
7
8
9
10
11
12
13
// 区分四个节点类型
// html
document.nodeType // 9
// 元素
let el = document.querySelector('.cl1)
el.nodeType // 1
// 属性
el.getAttributeNode('class') // class="cl1"
el.getAtttibuteNode('id') // id="id1"
el.getAttributeNode('class').nodeType // 2
// 文本
el.firstChild // 'text1'
e.firstChild.nodeType // 3

伪数组转换为真数组

1
2
3
4
5
6
7
8
9
10
11
<li class="cl1" id="id1">test1</li>
<li>test2</li>
<li>test3</li>

const lis = document.getElementByTagName('li') // 伪数组
console.log(lis instanceof Array, lis[1].innerHTML, lis.forEach) // false, 'test1', undefined
// 转换为真数组
const lis2 = Array.prototype.slice.call(lis)
const lis3 = [].slice.call(lis)
const lis4 = Array.from(lis)
console.log(lis2 instanceof Array, lis2[1].innerHTML, lis.forEach) // true, 'test1', function

Object.defineProperty(obj, ‘key’, {})

实现vue的监听数据的作用,支持IE9以上,所以vue不支持IE8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {}
Object.defineProperty(obj, 'fullName', {
configurable: false,
enumerable: false,
get () {
return this.firstName + ' ' + this.lastName
},
set (val) {
let name = val.split(' ')
this.firstName = name[0]
this.lastName = name[1]
}
})
obj.firstName = 'zhuang'
obj.lastName = 'cheng'
obj.fullName // 'zhuang cheng'
obj.fullName = 'Ethan cheng'
obj.firstName // 'Ethan'
obj.lastName // 'cheng'

DocumentFragment

文档碎片,高效批量更新多个节点
document // 对应显示的页面,包含所有element节点,一旦某个节点更新,界面就需要更新
documentFragment // 内存中保存n个element的容器对象,如果更新documentFragment中的元素,页面不会立即更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>

const ul = document.querySelector('ul')
// 1、创建documentFragment
const fragment = document.createDocumentFragment()
// 2、取出document里的所有节点,保存到documentFragment
let child
while (child = ul.firstChild) { // 一个节点只能有一个父元素, 所以先将child从ul中移出,再添加到fragment中
fragment.appendChild(child)
}
// 3、执行fragment中的元素
Array.prototype.slice.call(fragment).forEach(node => {
if (node.nodeType === 1) {
node.textContent = 'afsdf'
}
})
// 4、将fragment重新添加到ul中
ul.appendChild(fragment)